﻿// <copyright file="Text.cs" company="Microsoft Corporation">
// Copyright (c) 2008 All Right Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2009-01-30</date>
// <summary>Text class for IgnoreWhitespace Custom Attached Property</summary>

namespace Synergist
{
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;

    /// <summary>
    /// IgnoreWhitespace Custom Attached Property container class
    /// </summary>
    public sealed class Text
    {
        #region Fields
        /// <summary>
        /// IgnoreWhitespace dependency property
        /// </summary>
        public static readonly DependencyProperty IgnoreWhiteSpaceProperty =
            DependencyProperty.RegisterAttached(
            "IgnoreWhiteSpace",
            typeof(bool),
            typeof(Text),
            new PropertyMetadata(false, new PropertyChangedCallback(OnPropertyChanged)));

        #endregion

        #region Constructors
        /// <summary>
        /// Prevents a default instance of the Text class from being created.
        /// </summary>
        private Text()
        {
        }
        #endregion

        #region Methods

        /// <summary>
        /// Get the ignore whitespace property value
        /// </summary>
        /// <param name="source">the dependency object</param>
        /// <returns>whether to ignore the whitespace</returns>
        public static bool GetIgnoreWhiteSpace(DependencyObject source)
        {
            return (bool)source.GetValue(IgnoreWhiteSpaceProperty);
        }

        /// <summary>
        /// Set the ignore whitespace property value
        /// </summary>
        /// <param name="source">a dependency object</param>
        /// <param name="value">whether to ignore the whitespace</param>
        public static void SetIgnoreWhiteSpace(DependencyObject source, bool value)
        {
            source.SetValue(IgnoreWhiteSpaceProperty, value);
        }

        #endregion

        #region Implementation

        /// <summary>
        /// property changed event handler
        /// </summary>
        /// <param name="element">the dependency object (a TextBlock)</param>
        /// <param name="args">the dependency property changed event arguments</param>
        /// <remarks>When the property changes on loading the inline collection is not yet full.  we must wait until the whole element loads.</remarks>
        private static void OnPropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs args)
        {
            var textBlock = element as TextBlock;

            if (textBlock != null)
            {
                textBlock.Loaded += new RoutedEventHandler(OnTextBlockLoaded);

                UpdateInlines(textBlock.Inlines);
            }
        }

        /// <summary>
        /// Update the inlines when the textbox loads
        /// </summary>
        /// <param name="sender">the textblock</param>
        /// <param name="e">the routed event arguments</param>
        private static void OnTextBlockLoaded(object sender, RoutedEventArgs e)
        {
            var textBlock = sender as TextBlock;

            bool ignoreWhitespace = (bool)textBlock.GetValue(IgnoreWhiteSpaceProperty);

            if (ignoreWhitespace)
            {
                UpdateInlines(textBlock.Inlines);
            }
        }

        /// <summary>
        /// Remove all Run elements with a Text=" "
        /// </summary>
        /// <param name="inlines">an inline collection</param>
        private static void UpdateInlines(InlineCollection inlines)
        {
            bool removed = false;

            do
            {
                removed = false;

                foreach (var inline in inlines)
                {
                    var run = inline as Run;

                    if (run != null)
                    {
                        if (run.Text == " ")
                        {
                            inlines.Remove(run);
                            removed = true;
                            break;
                        }
                    }
                }
            }
            while (removed);
        }

        #endregion
    }
}
